<script setup>
import { videoGetService } from '@/api/video';
import { throttle } from '@/utils/lodash';
import { ref, onMounted, onUnmounted, watch } from 'vue';

/* 获取视频 */
let globalId = 1; // 全局唯一id
const videoViewRef = ref(null);
const videoListRef = ref(null);
const videoList = ref([]);

async function getVideoList() {
  const res = await videoGetService();
  const newVideoList = res.data.data;

  // 给每个video加上全局唯一id
  for (const video of newVideoList) {
    video._uid = globalId++;
  }

  videoList.value.push(...newVideoList);
}
getVideoList();

/* 观察者（观察当前Video变化【也代表视频滑动】） */
const observer = createObserver(); // 观察者实例
let curVideo = null; // 当前的Video
const curYXVideoRef = ref(null); // 当前的YXVideo
const videoToYXVideoMap = new Map(); // video映射对应的YXVideo

function createObserver() {
  return new IntersectionObserver(entries => {
    entries.forEach(entry => {
      // 进入可视窗口的视频
      if (entry.isIntersecting) {
        curVideo = entry.target;
        curYXVideoRef.value = videoToYXVideoMap.get(entry.target);
      }
    })
    // 这里可对视频进行清理操作
  }, 
  {
    threshold: 1,
    rootMargin: '0px',
    root: null 
  })
}

function observeVideo(yxVideo, _uid) {
  if (yxVideo == null) return;

  // 获取YXVideo中的原生视频标签
  const videoTag = yxVideo.$el.querySelector('video');
  // 原生视频标签绑定_uid
  videoTag.dataset._uid = _uid;
  // 建立映射关系
  videoToYXVideoMap.set(videoTag, yxVideo);
  // 观察原生标签（或许观察组件的根标签也行）
  observer.observe(videoTag);
}

function unobserveVideo(yxVideo, _uid) {
  observer.unobserve(yxVideo);
}

onUnmounted(() => {
  observer.disconnect();
})

/* 观察者（观察当前YXVideo变化【也代表视频滑动】） */
watch(curYXVideoRef, (newYXVideo, oldYXVideo) => {
  // 旧视频暂停，新视频播放
  if (oldYXVideo) {
    oldYXVideo.pause();
  }
  newYXVideo.play();
})

/* 处理上或下的handler */
function upHandler() {
  // 当前为顶部
  if (curVideo.dataset._uid == videoList.value[0]._uid) { 
    return;
  }

  idx.value++;
}

function downHandler() {
  // 如果快到达底部则获取更多视频
  if (videoList.value.length - 2 >= 0 && curVideo.dataset._uid >= videoList.value[videoList.value.length - 2]._uid) { // 理论上视频数一定大于1的
    getVideoList();
  }
  
  // 当前为底部
  if (curVideo.dataset._uid == videoList.value[videoList.value.length - 1]._uid) {
    return;
  }

  idx.value--;
}

/* 处理全屏事件 */
function fullscreenHandler() {
  videoViewRef.value.requestFullscreen().catch(err => {
    console.error(`全屏请求错误: ${err.message}`);
  });
}

/* 监听键盘事件 */
const idx = ref(0); // 记录全局索引（主要用于调整list的滑动距离）
function keyDownListener(event) {
  // 空格控制播放与暂停
  if (event.key === ' ') {
    curYXVideoRef.value.togglePlayPause();
  } else if (event.key === 'ArrowUp') {
    upHandler();
  } else if (event.key == 'ArrowDown') {
    downHandler();
  }
}
const throttleKeyDownListener = throttle(keyDownListener, 400);
document.addEventListener('keydown', throttleKeyDownListener);

// 移除事件监听
onUnmounted(() => {
  document.removeEventListener('keydown', throttleKeyDownListener);
})

/* 监听滚轮事件 */
function wheelListener(e) {
  if (e.deltaY <= -10) {
    upHandler();
  } else if (e.deltaY >= 10) {
    downHandler();
  }
}
const throttleWheelListener = throttle(wheelListener, 800);
document.addEventListener('wheel', throttleWheelListener);

// 移除事件监听
onUnmounted(() => {
  document.removeEventListener('wheel', throttleWheelListener);
})

</script>


<template>
  <div ref="videoViewRef" class="video-view">
    <div ref="videoListRef" class="video-list"
    :style="{ transform: `translateY(${idx * 100}%)` }">
      <yx-video
      :ref="(e) => observeVideo(e, video._uid)"
      :src="video.url"
      :videoId="video.id"
      :creatorId="video.creatorId"
      :creatorName="video.creatorName"
      :creatorAvatar="video.creatorAvatar"
      :description="video.description"
      :likes="video.likes"
      :comments="video.comments"
      :favorites="video.favorites"
      :is-followed="video.isFollowed"
      :is-liked="video.isLike"
      :is-favorited="video.isFavorite"
      :key="video._uid"
      @request-fullscreen="fullscreenHandler"
      v-for="video in videoList"></yx-video>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.video-view {
  height: 100%;
  width: 80%;
  margin: 0 auto;
  overflow: hidden;
  .video-list {
    z-index: 1;
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: center;
    height: 100%;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
}
</style>